#include "mainwidget.h"
#include "ui_mainwidget.h"

MainWidget::MainWidget(QWidget *parent) :
	QWidget(parent),
	ui(new Ui::MainWidget)
{
	ui->setupUi(this);

	availableIconThemes << "Tango" <<
						   "Elementary Xfce Dark";

	iconFile.open();
	qDebug() << iconFile.fileName();
	trayIcon = new QSystemTrayIcon(this);
	connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
			this, SLOT(onTrayIconActivated(QSystemTrayIcon::ActivationReason)));
	trayIcon->installEventFilter(this);
	populateCmbIcons();
	refresh();
	trayIcon->show();
	resize(sizeHint());
	hide();
}

MainWidget::~MainWidget()
{
	delete ui;
}

void MainWidget::populateCmbIcons()
{
	ui->cmbIcon->setUpdatesEnabled(false);
	ui->cmbIcon->clear();
	foreach (QString theme, availableIconThemes) {
		ui->cmbIcon->addItem(theme);
	}
	QString currentIconTheme = getIconTheme();
	int index = qMax(0, availableIconThemes.indexOf(currentIconTheme));
	ui->cmbIcon->setCurrentIndex(index);
	ui->cmbIcon->setUpdatesEnabled(true);
}

void MainWidget::changeEvent(QEvent* e)
{
	switch (e->type()) {
		case QEvent::LanguageChange: {
			this->ui->retranslateUi(this);
			break;
		}
		case QEvent::WindowStateChange: {
			if (this->windowState() & Qt::WindowMinimized) {
				QTimer::singleShot(50, this, SLOT(hide()));
			}
			break;
		}
		default:
			break;
	}
	QWidget::changeEvent(e);
}

void MainWidget::closeEvent(QCloseEvent *event)
{
	event->ignore();
	QTimer::singleShot(50, this, SLOT(hide()));
}

void MainWidget::showEvent(QShowEvent *)
{
	QTimer::singleShot(50, this, SLOT(onShow()));
}

void MainWidget::refresh()
{
	updateVolume();
	updateGui();
}

void MainWidget::onShow()
{
	refresh();
}

bool MainWidget::eventFilter(QObject *obj, QEvent *event)
{
	if (event->type() == QEvent::Wheel) {
		QWheelEvent *wheelEvent = dynamic_cast<QWheelEvent*>(event);
		if (wheelEvent) {
			int numDegrees = wheelEvent->delta() / 8;
			int numSteps = numDegrees / 15;
			onTrayIconWheel(numSteps);
			return true;
		}
	}
	return QObject::eventFilter(obj, event);
}

bool MainWidget::runCommand(QString program, QStringList arguments,
							QString &stdout, QString stderr)
{
	stdout.clear();
	stderr.clear();

	QProcess p;
	p.setProcessChannelMode(QProcess::SeparateChannels);
	p.start(program, arguments);
	if (!p.waitForStarted())
		return false;

	p.closeWriteChannel();

	if (!p.waitForFinished())
		return false;

	stdout = p.readAllStandardOutput();
	stderr = p.readAllStandardError();
	return p.exitCode() == 0;
}

bool MainWidget::runCommand(QString program, QStringList arguments)
{
	QString out, err;
	return runCommand(program, arguments, out, err);
}

void MainWidget::showNotification(QString title, QString text, int durationMs)
{
	if (!runCommand("notify-send",
					QStringList() <<
					"-i" << iconFile.fileName() <<
					"-u" << "normal" <<
					"-t" << QString("%1").arg(100 + durationMs) <<
					"-a" << "qvolume" <<
					title << text)) {
		trayIcon->showMessage(title, text, QSystemTrayIcon::NoIcon, durationMs);
	}
}

void MainWidget::updateVolume()
{
	if (runCommand("pamixerz", QStringList())) {
		QString out, err;
		runCommand("pamixer", QStringList() << "--get-mute", out, err);
		muted = out == "true";

		runCommand("pamixer", QStringList() << "--get-volume", out, err);
		bool ok;
		volume = out.toDouble(&ok) / 100.0;
		if (!ok) {
			volume = 1.0;
		}
	} else {
		// fallback to amixer
		QString out, err;
		runCommand("amixer", QStringList() << "get" << "Master", out, err);

		QStringList lines = out.split('\n');

		foreach (QString line, lines) {
			if (line.contains("Playback") && line.contains("%]") &&
				(line.contains("[on]") || line.contains("[off]"))) {
				muted = line.contains("[off]");
				bool ok;
				qreal v = line.split('%').first()
						  .split('[').last().toDouble(&ok);
				if (ok) {
					volume = v / 100;
				}
				qDebug() << line << volume << muted;
			}
		}
	}
}

void MainWidget::setVolume()
{
	volume = qMin(1.0, volume);
	volume = qMax(0.0, volume);
	if (runCommand("pamixerz", QStringList())) {
		runCommand("pamixer",
				   QStringList() <<
				   (muted ? "--mute" : "--unmute"));
		runCommand("pamixer",
				   QStringList() <<
				   "--set-volume" <<
				   QString("%1").arg(qRound(volume * 100)));
	} else {
		runCommand("amixer",
				   QStringList() << "set" << "Master" << "Playback" <<
				   (muted ? "off" : "on"));
		runCommand("amixer",
				   QStringList() << "set" << "Master" << "Playback" <<
				   QString("%1%").arg(qRound(volume * 100)));
	}
	updateVolume();
}

void MainWidget::adjustVolume(int numSteps)
{
	updateVolume();
	volume += numSteps * 0.05;
	setVolume();
	updateGui();
}

void MainWidget::toggleMute()
{
	updateVolume();
	muted = !muted;
	setVolume();
	updateGui();
}

void MainWidget::updateGui()
{
	QString iconPath = getIconPath();
	QFile resourceFile(iconPath);
	resourceFile.open(QFile::ReadOnly);
	QByteArray data = resourceFile.readAll();
	iconFile.seek(0);
	iconFile.resize(0);
	while (!data.isEmpty()) {
		qint64 count = iconFile.write(data);
		if (count < 0) {
			break;
		}
		data = data.mid(count);
	}
	iconFile.flush();
	trayIcon->setIcon(QIcon(iconPath));
	setWindowIcon(QIcon(iconPath));
	ui->checkMute->setChecked(muted);
	trayIcon->setToolTip(QString("Volume: %1% %2\n"
								 "\n"
								 "Use the mouse wheel on the tray icon to change the volume.\n"
								 "Use the middle button to toggle mute.")
						 .arg(qRound(volume * 100))
						 .arg(muted ? "muted" : ""));
}

void MainWidget::onTrayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
	if (reason == QSystemTrayIcon::Trigger) {
		onTrayIconLeftClick();
	} else if (reason == QSystemTrayIcon::MiddleClick) {
		onTrayIconMiddleClick();
	} else if (reason == QSystemTrayIcon::Context) {
		onTrayIconRightClick();
	} else if (reason == QSystemTrayIcon::DoubleClick) {
		onTrayIconDoubleClick();
	} else {
		onTrayIconLeftClick();
	}
}

void MainWidget::onTrayIconLeftClick()
{
	setVisible(!isVisible());
}

void MainWidget::onTrayIconMiddleClick()
{
	toggleMute();
}

void MainWidget::onTrayIconRightClick()
{
	setVisible(!isVisible());
}

void MainWidget::onTrayIconDoubleClick()
{
}

void MainWidget::onTrayIconWheel(int numSteps)
{
	adjustVolume(numSteps);
}

void MainWidget::on_btnDecreaseVolume_clicked()
{
	adjustVolume(-1);
}

void MainWidget::on_btnIncreaseVolume_clicked()
{
	adjustVolume(1);
}

void MainWidget::on_checkMute_toggled(bool checked)
{
	if (muted == checked)
		return;
	muted = checked;
	setVolume();
}

QString MainWidget::getIconTheme()
{
	return settings.value("iconTheme", availableIconThemes.first()).toString();
}

void MainWidget::setIconTheme(QString value)
{
	settings.setValue("iconTheme", value);
	settings.sync();
}

QString MainWidget::getIconPath()
{
	QString theme = getIconTheme();
	const qreal medium = 0.25;
	const qreal high = 0.50;
	if (theme == "Tango") {
		if (muted) {
			return ":/icons/audio-volume-muted.png";
		} else if (volume < medium) {
			return ":/icons/audio-volume-low.png";
		} else if (volume < high) {
			return ":/icons/audio-volume-medium.png";
		} else {
			return ":/icons/audio-volume-high.png";
		}
	} else if (theme == "Elementary Xfce Dark") {
		if (muted) {
			return ":/icons/audio-volume-muted-white.svg";
		} else if (volume < medium) {
			return ":/icons/audio-volume-low-white.svg";
		} else if (volume < high) {
			return ":/icons/audio-volume-medium-white.svg";
		} else {
			return ":/icons/audio-volume-high-white.svg";
		}
	} else {
		if (muted) {
			return ":/icons/audio-volume-muted.png";
		} else if (volume < medium) {
			return ":/icons/audio-volume-low.png";
		} else if (volume < high) {
			return ":/icons/audio-volume-medium.png";
		} else {
			return ":/icons/audio-volume-high.png";
		}
	}
}

void MainWidget::on_cmbIcon_currentIndexChanged(int index)
{
	if (index < 0 || index > availableIconThemes.count())
		return;
	if (!ui->cmbIcon->updatesEnabled())
		return;
	setIconTheme(availableIconThemes[index]);
	updateGui();
}

void MainWidget::on_btnExit_clicked()
{
	qApp->quit();
}
